#pragma once
#include "vector3.h"
#include <string>

namespace krryn{
namespace view{
	class heightmap{
	public:
		static heightmap* get_instance(){
			static heightmap* l_Heightmap = 0; 
			if(!l_Heightmap) 
				l_Heightmap = new heightmap("heightmap.bmp"); 
			return l_Heightmap;
		}

	public:
		float* get_buffer() const{return m_HeightPoints;}
		math::vector3f scale() const{return m_Scale;}
		int get_width() const{return m_Width;}
		int get_depth() const{return m_Depth;}
		float center_x() const{return get_width() / 2 - get_width();}
		float center_y() const{return -m_Scale.m_Y / 2 + m_Scale.m_Y;}
		float center_z() const{return -get_depth() / 2 + get_depth();}

		math::vector3f random_point() const{
			int x = ::rand() % get_width();
			int z = (::rand() % get_depth());

			float l_X = x + center_x();
			float l_Z = z - center_z();

			return math::vector3f(l_X, m_HeightPoints[z * get_width() + x], l_Z) * m_Scale;
		}

		float get_height(float a_X, float a_Y) const{
			float l_CX = center_x();
			float l_CY = center_z();

			return center_y() - m_HeightPoints[
				static_cast<int>(
					(a_Y / m_Scale.m_Z) + l_CY
				) * get_width() + static_cast<int>(
					(a_X / m_Scale.m_X) - l_CX
				) % (get_width() * get_depth())
			] * m_Scale.m_Y ;

			return m_Scale.m_Y;
		}
	
	private:
		heightmap(const std::string &a_Filename)
			: m_Filename(a_Filename), m_Scale(2.5f, 50, 2.5f) {generate();}
		~heightmap(){delete m_HeightPoints, m_HeightPoints = 0;}

		void generate();
		math::vector3f m_Scale;
		const std::string m_Filename;
		float *m_HeightPoints;
		int m_Width, m_Depth;
	};
};
}
